package com.todo.strategy.offline.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.todo.common.common.entity.response.BizResponse;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.enums.EnableTypeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.common.utils.TodoCommonUtils;
import com.todo.component.redis.RedisService;
import com.todo.strategy.common.constant.StrategyOfflineKeyBuild;
import com.todo.strategy.offline.application.convert.MemoTemplateConvert;
import com.todo.strategy.offline.application.entity.bo.MemoTemplateBO;
import com.todo.strategy.offline.application.entity.condition.MemoTemplateConditionBO;
import com.todo.strategy.offline.application.remote.StrategyPipelineRemoteService;
import com.todo.strategy.offline.application.service.MemoTemplateService;
import com.todo.strategy.offline.infrastructure.entity.condition.MemoTemplateCondition;
import com.todo.strategy.offline.infrastructure.entity.domain.MemoTemplateContentDO;
import com.todo.strategy.offline.infrastructure.repository.MemoTemplateRepository;
import com.todo.strategy.pipeline.common.enums.OperateActionEnum;
import com.todo.strategy.pipeline.common.enums.StrategyActionEnum;
import com.todo.strategy.pipeline.service.api.request.OfflineToOnlineRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.stream.Collectors;

/**
 * @author azhebuxing
 * @date 2024/11/28 02:35
 * @description
 */
@Slf4j
@Service
public class MemoTemplateServiceImpl implements MemoTemplateService {

    @Resource
    private MemoTemplateRepository memoTemplateRepository;
    @Resource
    private RedisService redisService;
    @Resource
    private StrategyPipelineRemoteService strategyPipelineRemoteService;

    @Override
    public Boolean insertMemoTemplate(MemoTemplateBO memoTemplateBO) {
        if (memoTemplateBO == null) {
            log.error("MemoTemplateService#insertMemoTemplate 新增备忘录数据失败，数据为空");
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        MemoTemplateContentDO memoTemplateContentDO = MemoTemplateConvert.convertToMemoTemplateContentDO(memoTemplateBO);
        Boolean insertResult = memoTemplateRepository.insertMemoTemplate(memoTemplateContentDO);
        if (insertResult) {
            String key = StrategyOfflineKeyBuild.memoTemplateKey(memoTemplateBO.getId());
            redisService.set(key, JSONObject.toJSONString(memoTemplateBO));
            postHandle(memoTemplateBO.getId(), OperateActionEnum.INSERT);
        }
        log.info("MemoTemplateService#insertMemoTemplate 新增备忘录数据完成，入参数：{},结果：{}", JSONObject.toJSONString(memoTemplateBO), insertResult);
        return insertResult;
    }

    @Override
    public Boolean updateMemoTemplate(MemoTemplateBO memoTemplateBO) {
        if (memoTemplateBO == null) {
            log.error("MemoTemplateService#updateMemoTemplate 更新备忘录数据失败，数据为空");
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        MemoTemplateBO alreadyMemoTemplateBO = queryMemoTemplateById(memoTemplateBO.getId());
        if (alreadyMemoTemplateBO == null) {
            log.error("MemoTemplateService#updateMemoTemplate 更新备忘录数据失败，数据不存在 memoTemplateBO:{}", JSONObject.toJSONString(memoTemplateBO));
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST, "数据不存在");
        }
        if (!alreadyMemoTemplateBO.getIsPlatform()) {
            log.error("MemoTemplateService#updateMemoTemplate 更新备忘录数据失败，非平台数据无法操作 memoTemplateBO:{}", JSONObject.toJSONString(memoTemplateBO));
            throw new BizException(BizErrorCodeEnum.ILLEGAL_OPERATION, "非平台数据无法操作");
        }
        if (EnableTypeEnum.ENABLE.equals(alreadyMemoTemplateBO.getStatus())) {
            log.error("MemoTemplateService#updateMemoTemplate 更新备忘录数据失败，启用状态下无法操作 memoTemplateBO:{}", JSONObject.toJSONString(memoTemplateBO));
            throw new BizException(BizErrorCodeEnum.ILLEGAL_OPERATION, "启用状态下无法操作");
        }
        MemoTemplateContentDO memoTemplateContentDO = MemoTemplateConvert.convertToMemoTemplateContentDO(memoTemplateBO);
        Boolean updated = memoTemplateRepository.updateMemoTemplate(memoTemplateContentDO);
        if (updated) {
            String key = StrategyOfflineKeyBuild.memoTemplateKey(memoTemplateBO.getId());
            redisService.del(key);
            postHandle(memoTemplateBO.getId(), OperateActionEnum.UPDATE);
        }
        log.info("MemoTemplateService#updateMemoTemplate 更新备忘录完成，入参：{},出参：{}", JSONObject.toJSONString(memoTemplateBO), updated);
        return updated;
    }

    @Override
    public Boolean removeMemoTemplateById(Long id) {
        if (id == null || id < 0) {
            log.error("MemoTemplateService#removeMemoTemplateById 删除备忘录数据失败，异常或者为空");
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "异常或者为空");
        }
        Boolean removed = memoTemplateRepository.removeMemoTemplateContentDOById(id);
        if (removed) {
            String key = StrategyOfflineKeyBuild.memoTemplateKey(id);
            redisService.del(key);
            postHandle(id, OperateActionEnum.REMOTE);
        }
        log.info("MemoTemplateService#removeMemoTemplateById 删除备忘录完成，入参：{},出参：{}", id, removed);
        return removed;
    }

    @Override
    public MemoTemplateBO queryMemoTemplateById(Long id) {
        if (id == null || id < 0) {
            log.error("MemoTemplateService#queryMemoTemplateById 查询备忘录数据失败，异常或者为空");
            return null;
        }
        String key = StrategyOfflineKeyBuild.memoTemplateKey(id);
        String cached = redisService.get(key);
        if (StringUtils.isNotEmpty(cached)) {
            MemoTemplateBO memoTemplateBO = JSONObject.parseObject(cached, MemoTemplateBO.class);
            log.info("MemoTemplateService#queryMemoTemplateById 缓存查询备忘录数据完成，入参：{},出参：{}", id, JSONObject.toJSONString(memoTemplateBO));
            return memoTemplateBO;
        }
        MemoTemplateContentDO memoTemplateContentDO = memoTemplateRepository.queryMemoTemplateContentDOById(id);
        if (memoTemplateContentDO == null) {
            log.warn("MemoTemplateService#queryMemoTemplateById 查询备忘录数据失败，数据为空 ID：{}", id);
            return null;
        }
        MemoTemplateBO memoTemplateBO = MemoTemplateConvert.convertToMemoTemplateBO(memoTemplateContentDO);
        redisService.set(key, JSONObject.toJSONString(memoTemplateBO));
        log.info("MemoTemplateService#queryMemoTemplateById 数据库查询备忘录数据完成，入参：{},出参：{}", id, JSONObject.toJSONString(memoTemplateBO));
        return memoTemplateBO;
    }

    @Override
    public Boolean updateMemoStatusById(Long id, EnableTypeEnum oldStatus, EnableTypeEnum newStatus) {
        if (id == null || id < 0 || oldStatus == null || newStatus == null || oldStatus == newStatus) {
            log.error("MemoTemplateService#updateMemoStatusById 根据主键更新备忘录状态失败，异常或者为空");
            return false;
        }
        MemoTemplateBO memoTemplateBO = queryMemoTemplateById(id);
        if (memoTemplateBO == null) {
            log.error("MemoTemplateService#updateMemoStatusById 根据主键更新备忘录状态失败，根据Id查询数据不存在 id:{}", id);
            throw new BizException(BizErrorCodeEnum.CONTENT_IS_NULL);
        }
        if (memoTemplateBO.getStatus().equals(newStatus)) {
            return true;
        }
        Boolean updated = memoTemplateRepository.updateMemoStatusById(id, oldStatus.getType(), newStatus.getType());
        if (updated) {
            String key = StrategyOfflineKeyBuild.memoTemplateKey(id);
            redisService.del(key);
            if (EnableTypeEnum.ENABLE.equals(newStatus)) {
                postHandle(memoTemplateBO.getId(), OperateActionEnum.ENABLE);
            }
            if (EnableTypeEnum.FORBIDDEN.equals(newStatus)) {
                postHandle(memoTemplateBO.getId(), OperateActionEnum.DISABLE);
            }
        }
        log.info("MemoTemplateService#updateMemoStatusById 根据主键更新备忘录状态完成，入参Id：{},oldType:{},newType:{},出参：{}", id, oldStatus, newStatus, updated);
        return updated;
    }

    @Override
    public PageResult<MemoTemplateBO> queryMemoTemplateByPage(MemoTemplateConditionBO memoTemplateConditionBO) {
        if (memoTemplateConditionBO == null) {
            log.error("MemoTemplateService#queryMemoTemplateByPage 查询备忘录数据失败，异常或者为空");
            return null;
        }
        MemoTemplateCondition condition = MemoTemplateConvert.convertToMemoTemplateCondition(memoTemplateConditionBO);
        PageResult<MemoTemplateContentDO> pageResult = memoTemplateRepository.queryMemoTemplatePOByCondition(condition);
        if (pageResult == null) {
            return new PageResult<>();
        }
        PageResult<MemoTemplateBO> result = new PageResult<>();
        result.setResults(pageResult.getResults() == null ? null : pageResult.getResults().stream().map(MemoTemplateConvert::convertToMemoTemplateBO).collect(Collectors.toList()));
        result.setPageCount(pageResult.getPageCount());
        result.setPageNum(pageResult.getPageNum());
        result.setPageSize(pageResult.getPageSize());
        result.setHasNext(pageResult.isHasNext());
        result.setCurrentIndex(pageResult.getCurrentIndex());
        result.setTotal(pageResult.getTotal());
        return result;
    }


    private void postHandle(Long templateId, OperateActionEnum operateActionEnum) {
        if (OperateActionEnum.REMOTE.equals(operateActionEnum)) {
            OfflineToOnlineRequest request = new OfflineToOnlineRequest();
            request.setBusinessId(templateId);
            request.setUniKey(TodoCommonUtils.buildStriHashKey(templateId, new Date()));
            request.setOperateActionEnum(operateActionEnum);
            request.setStrategyActionEnum(StrategyActionEnum.PLATFORM_MEMO);
            request.setOriginData(new JSONObject().toJSONString());
            BizResponse<Boolean> bizResponse = strategyPipelineRemoteService.offlineToOnlineAsync(request);
            if (bizResponse == null || !bizResponse.isSuccess() || !bizResponse.getData()) {
                log.error("MemoTemplateService#doStatusHandle 平台备忘录发布状态处理失败，数据同步失败 request:{}", JSONObject.toJSONString(request));
            }
        } else {
            MemoTemplateContentDO memoTemplateContentDO = memoTemplateRepository.queryMemoTemplateContentDOById(templateId);
            if (memoTemplateContentDO == null) {
                log.error("MemoTemplateService#postHandle 根据主键更新备忘录状态失败，根据Id查询数据不存在 id:{}", templateId);
                return;
            }
            OfflineToOnlineRequest request = new OfflineToOnlineRequest();
            request.setBusinessId(templateId);
            request.setUniKey(TodoCommonUtils.buildStriHashKey(templateId, memoTemplateContentDO.getUpdateTime()));
            request.setOperateActionEnum(operateActionEnum);
            request.setStrategyActionEnum(StrategyActionEnum.PLATFORM_MEMO);
            request.setOriginData(JSONObject.toJSONString(memoTemplateContentDO));
            BizResponse<Boolean> bizResponse = strategyPipelineRemoteService.offlineToOnlineAsync(request);
            if (bizResponse == null || !bizResponse.isSuccess() || !bizResponse.getData()) {
                log.error("MemoTemplateService#postHandle 平台备忘录发布状态处理失败，数据同步失败 request:{}", JSONObject.toJSONString(request));
            }
        }
    }
}
